package main

import (
	"encoding/json"
	"io"
	"sync"
	"time"
)

type UID string
type UIDs []UID

type Label struct {
	UID  UID `json:"uid"`
	Item UID `json:"item"`

	Name string `json:"name"`
	Desc string `json:"desc,omitempty"`
	Slug string `json:"slug,omitempty"`

	Modified time.Time `json:"modified"`
}

type Inheritable struct {
	InhLabel  bool `json:"inhlbl"`
	InhValue  bool `json:"inhval"`
	InhStatic bool `json:"static"`
}

type Field struct {
	UID   UID `json:"uid"`
	Label UID `json:"lbl"`
	Node  UID `json:"node"`

	Value string `json:"val"`

	Inheritable `json:"inh"`
	Modified    time.Time `json:"modified"`
}

type Relation struct {
	UID   UID `json:"uid"`
	Label UID `json:"lbl"`
	Node  UID `json:"node"`

	Related UIDs `json:"rels"`

	Inheritable `json:"inh"`
	Modified    time.Time `json:"modified"`
}

type Node struct {
	*Lexicon `json:"-"`

	UID   UID `json:"uid"`
	Label UID `json:"lbl"`

	Parents   UIDs `json:"parents,omitempty"`
	Children  UIDs `json:"children,omitempty"`
	Fields    UIDs `json:"fields"`
	Relations UIDs `json:"relations"`

	Modified time.Time `json:"modified"`
}

type Lexicon struct {
	NUID   uint64     `json:"nuid"`
	newUID <-chan UID `json:"-"`

	Nodes     map[UID]*Node     `json:"nodes"`
	Labels    map[UID]*Label    `json:"labels"`
	Fields    map[UID]*Field    `json:"fields"`
	Relations map[UID]*Relation `json:"relations"`
	Slugs     map[string]UID    `json:"slugs"`
}

func New() *Lexicon {
	lex := newLexicon()
	lex.init()
	return lex
}

func Load(r io.Reader) (*Lexicon, error) {
	lex := newLexicon()
	err := json.NewDecoder(r).Decode(lex)
	lex.init()
	return lex, err
}

func (lex *Lexicon) Save(w io.Writer) error {
	return json.NewEncoder(w).Encode(lex)
}
